﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Globalization;
using System.Runtime.Serialization;
using System.Xml;

namespace GeoTracer
{
    [DataContract]
    public class IPLocation
    {
        [DataMember]
        public string CountryCode { get; private set; }
        [DataMember]
        public string Country { get; private set; }
        [DataMember]
        public string City { get; private set; }
        [DataMember]
        public int RegionCode { get; private set; }
        [DataMember]
        public string RegionName { get; private set; }
        [DataMember]
        public double Longtitude { get; private set; }
        [DataMember]
        public double Latitude { get; private set; }
        [DataMember]
        public string Text { get; set; }
        [DataMember]
        public int Frequency { get; set; }

        public string Encoded { get; private set; }
        public bool Error { get; private set; }

        public IPLocation(string encoded)
        {
            Error = false;
            if (string.IsNullOrEmpty(encoded))
            {
                Country = "";
                CountryCode = "";
                City = "";
                RegionCode = 0;
                RegionName = "";
                Longtitude = 0;
                Latitude = 0;
                Error = true;
                return;
            }
            Encoded = encoded;

            string[] args = encoded.Split(',');
            Country = args[3] == null ? "" : args[3];
            CountryCode = args[2] == null ? "" : args[2];
            City = args[6] == null ? "" : args[6];
            int regCode = 0;
            int.TryParse(args[4], out regCode);
            RegionCode = regCode;
            RegionName = args[5] == null ? "" : args[5];
            try
            {
                Longtitude = Double.Parse(args[9], CultureInfo.InvariantCulture.NumberFormat);
                Latitude = Double.Parse(args[8], CultureInfo.InvariantCulture.NumberFormat);
            }
            catch
            {
                Longtitude = 0;
                Latitude = 0;
                Error = true;
            }
        }
    }

    public class ProbeInfo
    {
        public int Frequency { get; set; }
        public string IP { get; set; }
        public string ClientID { get; set; }
    }

    public class IPLookup
    {
        private static Hashtable database;
        private static bool databaseChanged = false;
        private static string newPath = @"C:\Users\Morten\Documents\database.db";
        private static string oldPath = @"C:\Users\Morten\Documents\database.db.old";

        public IPLookup()
        {
        }

        public static List<ProbeInfo> GetIps()
        {
            List<ProbeInfo> list = new List<ProbeInfo>();

            string[] names = { "satwtweb1-s1-mb.xml", "satwtweb1-s2-mb.xml", "satwtweb3-s1-mb.xml", "satwtweb3-s2-mb.xml" };
            foreach (string name in names)
            {
                XmlDocument doc = new XmlDocument();
                string path = @"C:\Users\Morten\Documents\" + name;
                doc.Load(path);
                foreach (XmlNode n in doc.ChildNodes[1])
                    if (n.Name == "MessageBrokers")
                    {
                        foreach (XmlNode n2 in n.ChildNodes)
                            if (n2.Name == "MessageBrokerInfo")
                            {
                                ProbeInfo pi = new ProbeInfo();
                                foreach (XmlNode n3 in n2.ChildNodes)
                                    if (n3.Name == "ClientIP")
                                        pi.IP = n3.InnerText;
                                    else if (n3.Name == "Frequency")
                                    {
                                        int f = 0;
                                        if (int.TryParse(n3.InnerText, out f))
                                            pi.Frequency = f;

                                    }
                                    else if (n3.Name == "ClientID")
                                        pi.ClientID = n3.InnerText;
                                list.Add(pi);
                            }
                    }
            }
            return list;
        }

        public static IPLocation DoLookup(string ip)
        {
            if (database == null)
                LoadDatabase();

            if (database.ContainsKey(ip))
            {
                IPLocation l = database[ip] as IPLocation;
                return l;
            }
            //string addr = string.Format("http://freegeoip.appspot.com/csv/{0}", ip);
            string addr = string.Format("http://freegeoip.net/csv/{0}", ip);
            WebRequest wr = HttpWebRequest.Create(addr);
            //WebProxy proxy = new WebProxy("http://proxy2.mid.dom:8080");
            //proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
            ////new NetworkCredential("mkg", "xxx", "sys");
            //wr.Proxy = proxy;

            try
            {
                wr.Method = "GET";
                WebResponse res = wr.GetResponse();
                Stream resStream = res.GetResponseStream();
                string response = new StreamReader(resStream).ReadToEnd();
                IPLocation location = new IPLocation(response);
                database.Add(ip, location);
                databaseChanged = true;
                return location;
            }
            catch (Exception ex)
            {
                return new IPLocation("");
            }


            //IAsyncResult result = null;
            //string responseText = string.Empty;
            //result = wr.BeginGetResponse(state => 
            //            {
            //                WebResponse response = wr.EndGetResponse(result);
            //                Stream resStream = response.GetResponseStream();
            //                responseText = new StreamReader(resStream).ReadToEnd();
            //            }
            //          , null);
            //return new IPLocation(responseText);
        }

        public static void LoadDatabase()
        {
            database = new Hashtable();
            try
            {
                StreamReader sr = File.OpenText(newPath);
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    int splitter = line.IndexOf(' ');
                    string ip = line.Substring(0, splitter);
                    string encoded = line.Substring(splitter + 1);
                    IPLocation location = new IPLocation(encoded);
                    database.Add(ip, location);
                }
                sr.Close();
            }
            catch { }
        }

        public static void SaveDatabase()
        {
            if (!databaseChanged)
                return;
            try
            {
                try
                {
                    File.Delete(oldPath);
                }
                catch { }
                File.Move(newPath, oldPath);
            }
            catch  // (FileNotFoundException)
            { }
            try
            {
                FileStream fs = File.OpenWrite(newPath);
                StreamWriter sw = new StreamWriter(fs);
                foreach (DictionaryEntry de in database)
                {
                    IPLocation location = de.Value as IPLocation;
                    if (location != null)
                        sw.WriteLine(string.Format("{0} {1}", de.Key, location.Encoded));
                }
                sw.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                int h;
            }
        }
    }
}